import datetime
from dataclasses import dataclass, field
from typing import List, Callable, Optional
from abc import ABC, abstractmethod

from bitstring import BitStream, BitArray

# 类型字长定义
BYTE = 8
WORD = 16
DWORD = 32
BCD = 8

# BCD[6]对应的时间格式定义
DATETIME_FMT = '%y%m%d%H%M%S'

# 标识符定义
FLAG_CODE_808 = 0x7e
FLAG_CODE_1078 = 0x30316364


# 格式化BitStream的格式化token
def formatter(fmt: str):
    lines = fmt.splitlines()
    res = ''
    for line in lines:
        s = line.find('=')
        e = line.find(',')
        if s < 0 or e < 0:
            res += line
            continue
        line = line.replace(line[s:e], '')
        res += line

    return res


# None替换为默认值
def ifn(obj, default):
    if obj is None:
        return default


class Functions:
    """
    一些函数定义
    """

    @staticmethod
    def av_parameter_setting() -> Callable:
        def func(data: str):
            data = BitStream(hex=data)
            parse_result = dict()
            fmt = formatter(f"""
                        hex:{BYTE}=stream_encoding_mode,
                        hex:{BYTE}=stream_resolution,
                        hex:{WORD}=stream_key_frame_delay,
                        hex:{BYTE}=stream_frame_rate,
                        hex:{DWORD}=stream_code_rate,
                        hex:{BYTE}=save_stream_encoding_mode,
                        hex:{BYTE}=save_stream_resolution,
                        hex:{WORD}=save_stream_key_frame_delay,
                        hex:{BYTE}=save_stream_frame_rate,
                        hex:{DWORD}=save_stream_code_rate,
                        hex:{WORD}=osd_sub_overlay,
                        hex:{BYTE}=enable_audio_output,
                        """)
            res = data.readlist(fmt)
            parse_result.setdefault("stream_encoding_mode", configs.stream_encoding_mode.get(res[0]))
            parse_result.setdefault("stream_resolution", configs.stream_resolution.get(res[1]))
            parse_result.setdefault("stream_key_frame_delay", int(res[2], base=16))
            parse_result.setdefault("stream_frame_rate", int(res[3], base=16))
            parse_result.setdefault("stream_code_rate", int(res[4], base=16))
            parse_result.setdefault("save_stream_encoding_mode", configs.stream_encoding_mode.get(res[5]))
            parse_result.setdefault("save_stream_resolution", configs.stream_resolution.get(res[6]))
            parse_result.setdefault("save_stream_key_frame_delay", int(res[7], base=16))
            parse_result.setdefault("save_stream_frame_rate", int(res[8], base=16))
            parse_result.setdefault("save_stream_code_rate", int(res[9], base=16))
            parse_result.setdefault("osd_sub_overlay", res[10])
            parse_result.setdefault("enable_audio_output", True if res[11] == '01' else False)

            return parse_result

        return func

    @staticmethod
    def av_channel_setting() -> Callable:
        def func(data: str):
            data = BitStream(hex=data)
            parse_result = dict()
            fmt = formatter(f"""
                        uint:{BYTE}=av_channel_total,
                        uint:{BYTE}=audio_channel_total,
                        uint:{BYTE}=video_channel_total,
                        hex=av_channel_chart,
                        """)
            res = data.readlist(fmt)
            parse_result.setdefault("av_channel_total", res[0])
            parse_result.setdefault("audio_channel_total", res[1])
            parse_result.setdefault("video_channel_total", res[2])
            parse_result.setdefault("av_channel_chart", list())

            data = BitStream(hex=res[3])
            fmt = formatter(f"""
                        hex:{BYTE}=physical_channel_no,
                        hex:{BYTE}=logical_channel_no,
                        hex:{BYTE}=channel_type,
                        hex:{BYTE}=connect_to_cloud,
                        """)
            count = 0
            while count < parse_result['av_channel_total'] + \
                    parse_result['audio_channel_total'] + parse_result['video_channel_total']:
                res = data.readlist(fmt)
                channel = {}
                channel.setdefault("physical_channel_no", res[0])
                channel.setdefault("logical_channel_no", res[1])
                channel.setdefault("channel_type", configs.channel_type.get(res[2]))
                channel.setdefault("connect_to_cloud", True if res[3] == '01' else False)
                parse_result["av_channel_chart"].append(channel)
                count += 1

            return parse_result

        return func

    @staticmethod
    def single_channel_setting() -> Callable:
        def func(data: str):
            data = BitStream(hex=data)
            parse_result = dict()
            fmt = formatter(f"""
                        uint:{BYTE}=parameter_total,
                        hex=parameters,
                        """)
            res = data.readlist(fmt)
            parse_result.setdefault("parameter_total", res[0])
            parse_result.setdefault("parameters", list())
            n = res[0]
            parse_result["parameter_total"] = n
            data = BitStream(hex=res[1])
            fmt = formatter(f"""
                        hex:{BYTE}=logical_channel_no,
                        hex:{BYTE}=stream_encoding_mode,
                        hex:{BYTE}=stream_resolution,
                        hex:{WORD}=stream_key_frame_delay,
                        hex:{BYTE}=stream_frame_rate,
                        hex:{DWORD}=stream_code_rate,
                        hex:{BYTE}=save_stream_encoding_mode,
                        hex:{BYTE}=save_stream_resolution,
                        hex:{WORD}=save_stream_key_frame_delay,
                        hex:{BYTE}=save_stream_frame_rate,
                        hex:{DWORD}=save_stream_code_rate,
                        hex:{WORD}=osd_sub_overlay,
                        """)
            count = 0
            while count < n:
                res = data.readlist(fmt)
                parameter = {}
                parameter.setdefault("logical_channel_no", res[0])
                parameter.setdefault("stream_encoding_mode", configs.stream_encoding_mode.get(res[1]))
                parameter.setdefault("stream_resolution", configs.stream_resolution.get(res[2]))
                parameter.setdefault("stream_key_frame_delay", int(res[3], base=16))
                parameter.setdefault("stream_frame_rate", int(res[4], base=16))
                parameter.setdefault("stream_code_rate", int(res[5], base=16))
                parameter.setdefault("save_stream_encoding_mode", configs.stream_encoding_mode.get(res[6]))
                parameter.setdefault("save_stream_resolution", configs.stream_resolution.get(res[7]))
                parameter.setdefault("save_stream_key_frame_delay", int(res[8], base=16))
                parameter.setdefault("save_stream_frame_rate", int(res[9], base=16))
                parameter.setdefault("save_stream_code_rate", int(res[10], base=16))
                parse_result["parameters"].append(parameter)
                count += 1

            return parse_result

        return func


class BaseSetting(ABC):
    @abstractmethod
    def to_hex(self) -> str:
        """
        将设置项按照协议要求转换为十六进制字符串
        Returns
        转换后的十六进制字符串
        """
        pass


@dataclass
class OsdSubOverlay:
    """
    OSD叠加设置
    多个设置项之间使用按位或运算符(|)连接
    Attributes:
        DATATIME: 叠加显示日期和时间
        LICENSE: 叠加显示车牌号
        LOGICAL_CHANNEL_NO: 叠加显示当前视频逻辑通道号
        RECORD_SPEED: 叠加显示车载记录的速度
        GPS_SPEED: 叠加显示定位给出的速度
        DRIVING_TIME: 叠加显示连续驾驶时长
    """
    DATATIME = 0x0001
    LICENSE = 0x0002
    LOGICAL_CHANNEL_NO = 0x0004
    LONGITUDE_LATITUDE = 0x0008
    RECORD_SPEED = 0x0010
    GPS_SPEED = 0x0020
    DRIVING_TIME = 0x0040


@dataclass
class AvParameterSetting(BaseSetting):
    """
    音视频参数设置（见jtt-1078-2016 表2）
    Attributes:
        stream_encoding_mode: str 实时流编码模式
        stream_resolution: str 实时流分辨率
        stream_key_frame_delay: int 实时流关键帧间隔
        stream_frame_rate: int 实时流目标帧率
        stream_code_rate: int 实时流目标码率
        save_stream_encoding_mode: str 存储流编码模式
        save_stream_resolution: str 存储流分辨率
        save_stream_key_frame_delay: int 存储流关键帧间隔
        save_stream_frame_rate: int 存储流目标帧率
        save_stream_code_rate: int 存储流目标码率
        osd_sub_overlay: int osd字母叠加设置，参见 :class:`OsdSubOverlay`
        enable_audio_output: bool 是否启用音频输出
    """
    stream_encoding_mode: str
    stream_resolution: str
    stream_key_frame_delay: int
    stream_frame_rate: int
    stream_code_rate: int
    save_stream_encoding_mode: str
    save_stream_resolution: str
    save_stream_key_frame_delay: int
    save_stream_frame_rate: int
    save_stream_code_rate: int
    osd_sub_overlay: int
    enable_audio_output: bool

    def to_hex(self):
        encoding_mode = {v: k for k, v in Configs().stream_encoding_mode.items()}
        resolution = {v: k for k, v in Configs().stream_resolution.items()}
        res = BitArray()
        res.append(BitArray(hex=encoding_mode[self.stream_encoding_mode]))
        res.append(BitArray(hex=resolution[self.stream_resolution]))
        res.append(BitArray(int=self.stream_key_frame_delay, length=WORD))
        res.append(BitArray(int=self.stream_frame_rate, length=BYTE))
        res.append(BitArray(int=self.stream_code_rate, length=DWORD))
        res.append(BitArray(hex=encoding_mode[self.save_stream_encoding_mode]))
        res.append(BitArray(hex=resolution[self.save_stream_resolution]))
        res.append(BitArray(int=self.save_stream_key_frame_delay, length=WORD))
        res.append(BitArray(int=self.save_stream_frame_rate, length=BYTE))
        res.append(BitArray(int=self.save_stream_code_rate, length=DWORD))
        res.append(BitArray(int=self.osd_sub_overlay, length=WORD))
        res.append(BitArray(hex='01' if self.enable_audio_output else '00'))

        return res.hex


@dataclass
class AvChannelChart(BaseSetting):
    """
    音视频通道对照表
    Attributes:
        physical_channel_no: int 物理通道号
        logical_channel_no: int 逻辑通道号
        channel_type: str 通道类型，见 :class:`Configs`
        connect_to_cloud: bool 是否连接到云台
    """
    physical_channel_no: int
    logical_channel_no: int
    channel_type: str
    connect_to_cloud: bool

    def to_hex(self):
        channel_type = {v: k for k, v in configs.channel_type.items()}
        res = BitArray()
        res.append(BitArray(int=self.physical_channel_no, length=BYTE))
        res.append(BitArray(int=self.logical_channel_no, length=BYTE))
        res.append(BitArray(hex=channel_type[self.channel_type]))
        res.append(BitArray(hex='01' if self.connect_to_cloud else '00'))

        return res.hex


@dataclass
class AvChannelSetting(BaseSetting):
    """
    音视频通道设置（见jtt-1078-2016表3）
    Attributes:
        av_channel_total: int 要设置的音视频通道总数
        audio_channel_total: int 要设置的音频通道总数
        video_channel_total: int 要设置的视频通道总数
        av_channel_charts: List[AvChannelChart] 每个通道的设置值，参见 :class:`AvChannelChart`
    """
    av_channel_total: int
    audio_channel_total: int
    video_channel_total: int
    av_channel_charts: List[AvChannelChart]

    def to_hex(self):
        res = BitArray()
        res.append(BitArray(int=self.av_channel_total, length=BYTE))
        res.append(BitArray(int=self.audio_channel_total, length=BYTE))
        res.append(BitArray(int=self.video_channel_total, length=BYTE))
        for av_channel_chart in self.av_channel_charts:
            res.append(BitArray(hex=av_channel_chart.to_hex()))

        return res.hex


@dataclass
class ChannelSetting(BaseSetting):
    """
    通道设置项
    Attributes:
        logical_channel_no: int 要设置通道的逻辑通道号
        stream_encoding_mode: str 实时流编码模式
        stream_resolution: str 实时流分辨率
        stream_key_frame_delay: int 实时流关键帧间隔
        stream_frame_rate: int 实时流目标帧率
        stream_code_rate: int 实时流目标码率
        save_stream_encoding_mode: str 存储流编码模式
        save_stream_resolution: str 存储流分辨率
        save_stream_key_frame_delay: int 存储流关键帧间隔
        save_stream_frame_rate: int 存储流目标帧率
        save_stream_code_rate: int 存储流目标码率
        osd_sub_overlay: int osd字母叠加设置，参见 :class:`OsdSubOverlay`
    """
    logical_channel_no: int
    stream_encoding_mode: str
    stream_resolution: str
    stream_key_frame_delay: int
    stream_frame_rate: int
    stream_code_rate: int
    save_stream_encoding_mode: str
    save_stream_resolution: str
    save_stream_key_frame_delay: int
    save_stream_frame_rate: int
    save_stream_code_rate: int
    osd_sub_overlay: int

    def to_hex(self) -> str:
        res = BitArray()
        res.append(BitArray(int=self.logical_channel_no, length=BYTE))
        encoding_mode = {v: k for k, v in Configs().stream_encoding_mode.items()}
        resolution = {v: k for k, v in Configs().stream_resolution.items()}
        res.append(BitArray(hex=encoding_mode[self.stream_encoding_mode]))
        res.append(BitArray(hex=resolution[self.stream_resolution]))
        res.append(BitArray(int=self.stream_key_frame_delay, length=WORD))
        res.append(BitArray(int=self.stream_frame_rate, length=BYTE))
        res.append(BitArray(int=self.stream_code_rate, length=DWORD))
        res.append(BitArray(hex=encoding_mode[self.save_stream_encoding_mode]))
        res.append(BitArray(hex=resolution[self.save_stream_resolution]))
        res.append(BitArray(int=self.save_stream_key_frame_delay, length=WORD))
        res.append(BitArray(int=self.save_stream_frame_rate, length=BYTE))
        res.append(BitArray(int=self.save_stream_code_rate, length=DWORD))
        res.append(BitArray(int=self.osd_sub_overlay, length=WORD))

        return res.hex


@dataclass
class SingleChannelSetting(BaseSetting):
    """
    单独通道设置（见jtt-1078-2016表5）
    Attributes:
        parameter_total: int 要设置的通道总数
        parameters: List[ChannelSetting] 设置项，参见 :class:`ChannelSetting`
    """
    parameter_total: int
    parameters: List[ChannelSetting]

    def to_hex(self) -> str:
        res = BitArray(int=self.parameter_total, length=BYTE).hex
        for parameter in self.parameters:
            res += parameter.to_hex()

        return res


@dataclass
class AudioVideoAttribute(BaseSetting):
    """
    音视频属性
    audio_encoding: str 音频编码方式
    audio_channel_num: int 音频声道数
    audio_adoption_rate: str 音频采样率
    audio_adoption_bit: str 音频采样位长
    audio_frame_length: int 音频帧长度
    support_audio_output: bool 是否支持音频输出
    video_encoding: str 视频编码方式
    max_audio_physical_channel_num: int 支持的最大音频物理通道数量
    max_video_physical_channel_num: int 支持的最大视频物理通道数量
    """
    audio_encoding: str
    audio_channel_num: int
    audio_adoption_rate: str
    audio_adoption_bit: str
    audio_frame_length: int
    support_audio_output: bool
    video_encoding: str
    max_audio_physical_channel_num: int
    max_video_physical_channel_num: int

    def to_hex(self) -> str:
        res = BitArray()
        encoding_table = {v: k for k, v in configs.audio_video_encoding}
        adoption_rate_table = {v: k for k, v in configs.audio_adoption_rate}
        adoption_bit_table = {v: k for k, v in configs.audio_adoption_bit}
        res.append(BitArray(int=encoding_table[self.audio_encoding], length=BYTE))
        res.append(BitArray(int=self.audio_channel_num, length=BYTE))
        res.append(BitArray(int=self.audio_adoption_rate, length=BYTE))
        res.append(BitArray(int=self.audio_adoption_bit, length=BYTE))
        res.append(BitArray(int=self.audio_frame_length, length=WORD))
        res.append(BitArray(hex=adoption_rate_table[self.audio_adoption_rate]))
        res.append(BitArray(hex=adoption_bit_table[self.audio_adoption_bit]))
        res.append(BitArray(hex="01" if self.support_audio_output else "00"))
        res.append(BitArray(int=encoding_table[self.video_encoding], length=BYTE))
        res.append(BitArray(int=self.max_audio_physical_channel_num, length=BYTE))
        res.append(BitArray(int=self.max_video_physical_channel_num, length=BYTE))

        return res.hex


@dataclass
class AudioVideoTransferRequest(BaseSetting):
    """
    音视频传输请求
    server_ip: str 上传目标服务器ip地址
    tcp_port: int 服务器TCP端口
    udp_port: int 服务器UDP端口
    logical_channel_no: int 逻辑通道数量
    data_type: int 传输的数据类型，是音频还是视频
    stream_type: int 码流类型，主码流还是副码流
    """
    server_ip: str
    tcp_port: int
    udp_port: int
    logical_channel_no: int
    data_type: int
    stream_type: int

    def to_hex(self) -> str:
        res = BitArray()
        res.append(BitArray(int=len(self.server_ip), length=BYTE))
        res.append(BitArray(self.server_ip.encode('gbk')))
        res.append(BitArray(int=self.tcp_port, length=WORD))
        res.append(BitArray(int=self.udp_port, length=WORD))
        res.append(BitArray(int=self.logical_channel_no, length=BYTE))
        res.append(BitArray(int=self.data_type, length=BYTE))
        res.append(BitArray(int=self.stream_type, length=BYTE))

        return res.hex


@dataclass
class AudioVideoTransferControl(BaseSetting):
    """
    音视频传输控制
    logical_channel_no: int 要控制的逻辑通道号
    command: int 对视频流进行什么控制
    close_audio_video: int  如果command指定了关闭传输命令，则此处指定具体关闭音频数据还是视频数据
    stream_type: int 如果command指定了切换码流类型，这里则指定要切换的码流类型
    """
    logical_channel_no: int
    command: int
    close_audio_video: int
    stream_type: int

    def to_hex(self) -> str:
        res = BitArray()
        res.append(BitArray(int=self.logical_channel_no, length=BYTE))
        res.append(BitArray(int=self.command, length=BYTE))
        res.append(BitArray(int=self.close_audio_video, length=BYTE))
        res.append(BitArray(int=self.stream_type, length=BYTE))

        return res.hex


@dataclass
class AudioAudioTransferStatus(BaseSetting):
    """
    音视频传输状态
    Attributes:
        logical_channel_no: int 状态相关的逻辑通道号
        pkt_loss: int 该通道音视频传输丢包率，数值为乘以100取整数部分
    """
    logical_channel_no: int
    pkt_loss: int

    def to_hex(self) -> str:
        res = BitArray()
        res.append(BitArray(int=self.logical_channel_no, length=BYTE))
        res.append(BitArray(int=self.pkt_loss, length=BYTE))

        return res.hex


@dataclass
class ResourceAttributes(BaseSetting):
    """
    资源属性，用于指定属性查找资源
    logical_channel_no: int 资源的逻辑通道号
    start_time: datetime.datetime 资源开始时间
    end_time: datetime.datetime 资源结束时间
    alert_flag: str 报警标志位，见jtt-1078-2016表21
    resource_type: int 资源类型，音频还是视频
    stream_type: int 码流类型，主码流还是子码流
    storage_type: int 资源所在的存储器类型，主存储器还是灾备存储器
    """
    logical_channel_no: int
    start_time: datetime.datetime
    end_time: datetime.datetime
    alert_flag: str
    resource_type: int
    stream_type: int
    storage_type: int

    def to_hex(self) -> str:
        res = BitArray()
        res.append(BitArray(int=self.logical_channel_no, length=BYTE))
        res.append(BitArray(hex=self.start_time.strftime(format=DATETIME_FMT)))
        res.append(BitArray(hex=self.end_time.strftime(format=DATETIME_FMT)))
        res.append(BitArray(bin=self.alert_flag))
        res.append(BitArray(int=self.resource_type, length=BYTE))
        res.append(BitArray(int=self.stream_type, length=BYTE))
        res.append(BitArray(int=self.storage_type, length=BYTE))

        return res.hex


@dataclass
class PlaybackControl(BaseSetting):
    """
    音视频回放控制
    """
    logical_channel_no: int
    playback_method: int = None
    control: int = None
    play_speed: int = None
    start_time: datetime.datetime = None
    end_time: datetime.datetime = None
    position: datetime.datetime = None

    def to_hex(self) -> str:
        res = BitArray()
        if self.logical_channel_no != -1:
            res.append(BitArray(int=self.logical_channel_no, length=BYTE))
        res.append(
            BitArray(int=self.playback_method if self.playback_method is not None else self.control, length=BYTE))
        res.append(BitArray(int=self.play_speed, length=BYTE))
        if self.position is not None:
            res.append(BitArray(hex=self.position.strftime(DATETIME_FMT)))
        else:
            res.append(BitArray(hex=self.start_time.strftime(format=DATETIME_FMT)))
            res.append(BitArray(hex=self.end_time.strftime(format=DATETIME_FMT)))

        return res.hex


@dataclass
class PlaybackRequest(PlaybackControl, AudioVideoTransferRequest):
    """
    远程录像回放请求
    """
    storage_type: int = None

    def to_hex(self) -> str:
        res = BitArray()
        res.append(BitArray(hex=AudioVideoTransferRequest.to_hex(self)))
        res.append(BitArray(int=self.storage_type, length=BYTE))
        res.append(BitArray(hex=PlaybackControl.to_hex(self)))

        return res.hex


@dataclass
class Configs:
    """
    硬编码的配置项，如某项的取值范围或某项的十六进制映射关系
    Attributes:
        stream_encoding_mode: 视频流编码模式
        stream_resolution: 视频流分辨率
        osd_sub_overlay: osd字母叠加配置
        channel_type: 通道类型
        terminal_parameter_configs: 设置终端参数时参数id与参数名以及参数映射函数的配置
        audio_video_encoding: 音视频编码表
    """
    stream_encoding_mode: dict = field(default_factory=lambda: {
        "00": "CBR",
        "01": "VBR",
        "02": "ABR",
    })
    stream_resolution: dict = field(default_factory=lambda: {
        "00": "QCIF",
        "01": "CIF",
        "02": "WCIF",
        "03": "D1",
        "04": "D2",
        "05": "720P",
        "06": "1080P",
    })
    osd_sub_overlay: dict = field(default_factory=lambda: [
        'datatime', 'license', 'channel', 'lat_long', 'record_speed', 'gps_speed', 'consecutive_time'
    ])
    channel_type: dict = field(default_factory=lambda: {
        "00": "audio_video",
        "01": "audio",
        "02": "video"
    })
    terminal_parameter_configs: dict = field(default_factory=lambda: {
        "0001": {
            "name": "keep_alive_interval",
            "mapping": lambda data: int(data, base=16)
        },
        "0002": {
            "name": "tcp_response_timeout",
            "mapping": lambda data: int(data, base=16)
        },
        "0003": {
            "name": "tcp_re_transfer_count",
            "mapping": lambda data: int(data, base=16)
        },
        "0004": {
            "name": "udp_response_timeout",
            "mapping": lambda data: int(data, base=16)
        },
        "0005": {
            "name": "udp_re_transfer_count",
            "mapping": lambda data: int(data, base=16)
        },
        "0006": {
            "name": "sms_response_timeout",
            "mapping": lambda data: int(data, base=16)
        },
        "0007": {
            "name": "sms_re_transfer_count",
            "mapping": lambda data: int(data, base=16)
        },
        "0010": {
            "name": "main_apn",
            "mapping": lambda data: BitArray(hex=data).tobytes().decode('gbk')
        },
        "0011": {
            "name": "main_apn_username",
            "mapping": lambda data: BitArray(hex=data).tobytes().decode('gbk')
        },
        "0012": {
            "name": "main_apn_password",
            "mapping": lambda data: BitArray(hex=data).tobytes().decode('gbk')
        },
        "0013": {
            "name": "main_apn_ip",
            "mapping": lambda data: BitArray(hex=data).tobytes().decode('gbk')
        },
        "0014": {
            "name": "backup_apn",
            "mapping": lambda data: BitArray(hex=data).tobytes().decode('gbk')
        },
        "0015": {
            "name": "backup_apn_username",
            "mapping": lambda data: BitArray(hex=data).tobytes().decode('gbk')
        },
        "0016": {
            "name": "backup_apn_password",
            "mapping": lambda data: BitArray(hex=data).tobytes().decode('gbk')
        },
        "0017": {
            "name": "backup_apn_ip",
            "mapping": lambda data: BitArray(hex=data).tobytes().decode('gbk')
        },
        "0018": {
            "name": "tcp_port",
            "mapping": lambda data: int(data, base=16)
        },
        "0019": {
            "name": "udp_port",
            "mapping": lambda data: int(data, base=16)
        },
        "0020": {
            "name": "position_report_policy",
            "mapping": lambda data: int(data, base=16)
        },
        "0021": {
            "name": "position_report_method",
            "mapping": lambda data: int(data, base=16)
        },
        "0022": {
            "name": "report_interval_when_nodriver",
            "mapping": lambda data: int(data, base=16)
        },
        "0027": {
            "name": "report_interval_when_sleep",
            "mapping": lambda data: int(data, base=16)
        },
        "0028": {
            "name": "report_interval_when_alert",
            "mapping": lambda data: int(data, base=16)
        },
        "0029": {
            "name": "report_interval_default",
            "mapping": lambda data: int(data, base=16)
        },
        "002c": {
            "name": "distance_report_interval_default",
            "mapping": lambda data: int(data, base=16)
        },
        "002d": {
            "name": "distance_report_interval_when_nodriver",
            "mapping": lambda data: int(data, base=16)
        },
        "002e": {
            "name": "distance_report_interval_when_sleep",
            "mapping": lambda data: int(data, base=16)
        },
        "002f": {
            "name": "distance_report_interval_when_alert",
            "mapping": lambda data: int(data, base=16)
        },
        "0030": {
            "name": "angle",
            "mapping": lambda data: int(data, base=16)
        },
        "0040": {
            "name": "supervisor_phone_no",
            "mapping": lambda data: BitArray(hex=data).tobytes().decode('gbk')
        },
        "0041": {
            "name": "reset_phone_no",
            "mapping": lambda data: BitArray(hex=data).tobytes().decode('gbk')
        },
        "0042": {
            "name": "factory_reset_phone_no",
            "mapping": lambda data: BitArray(hex=data).tobytes().decode('gbk')
        },
        "0043": {
            "name": "supervisor_sms_phone_no",
            "mapping": lambda data: BitArray(hex=data).tobytes().decode('gbk')
        },
        "0044": {
            "name": "alert_receiver_phone_no",
            "mapping": lambda data: BitArray(hex=data).tobytes().decode('gbk')
        },
        "0045": {
            "name": "phone_response_policy",
            "mapping": lambda data: int(data, base=16)
        },
        "0046": {
            "name": "max_call_duration",
            "mapping": lambda data: int(data, base=16)
        },
        "0047": {
            "name": "max_call_duration_month",
            "mapping": lambda data: int(data, base=16)
        },
        "0048": {
            "name": "monitor_phone_no",
            "mapping": lambda data: BitArray(hex=data).tobytes().decode('gbk')
        },
        "0049": {
            "name": "supervisor_privilege_sms_phone_no",
            "mapping": lambda data: BitArray(hex=data).tobytes().decode('gbk')
        },
        "0050": {
            "name": "alert_forbid_word",
            "mapping": lambda data: int(data, base=16)
        },
        "0051": {
            "name": "alert_sms_switch",
            "mapping": lambda data: int(data, base=16)
        },
        "0052": {
            "name": "alert_capturer_switch",
            "mapping": lambda data: int(data, base=16)
        },
        "0053": {
            "name": "alert_capturer_save_flag",
            "mapping": lambda data: int(data, base=16)
        },
        "0054": {
            "name": "key_flag",
            "mapping": lambda data: int(data, base=16)
        },
        "0055": {
            "name": "peak_speed",
            "mapping": lambda data: int(data, base=16)
        },
        "0056": {
            "name": "over_speed_time",
            "mapping": lambda data: int(data, base=16)
        },
        "0057": {
            "name": "consecutive_drive_time_threshold",
            "mapping": lambda data: int(data, base=16)
        },
        "0058": {
            "name": "day_total_drive_time_threshold",
            "mapping": lambda data: int(data, base=16)
        },
        "0059": {
            "name": "min_relax_time",
            "mapping": lambda data: int(data, base=16)
        },
        "005a": {
            "name": "max_park_time",
            "mapping": lambda data: int(data, base=16)
        },
        "0070": {
            "name": "media_quality",
            "mapping": lambda data: int(data, base=16)
        },
        "0071": {
            "name": "brightness",
            "mapping": lambda data: int(data, base=16)
        },
        "0072": {
            "name": "contrast",
            "mapping": lambda data: int(data, base=16)
        },
        "0073": {
            "name": "saturation",
            "mapping": lambda data: int(data, base=16)
        },
        "0074": {
            "name": "hue",
            "mapping": lambda data: int(data, base=16)
        },
        "0075": {
            "name": "av_parameter_setting",
            "mapping": None
        },
        "0076": {
            "name": "av_channel_setting",
            "mapping": None
        },
        "0077": {
            "name": "single_channel_setting",
            "mapping": None
        },
        "0079": {
            "name": "special_alert_capture_setting",
            "mapping": lambda data: data
        },
        "007a": {
            "name": "video_alter_forbid_word",
            "mapping": lambda data: data
        },
        "007b": {
            "name": "image_analysis_alert_setting",
            "mapping": lambda data: data
        },
        "007c": {
            "name": "sleep_awake_setting",
            "mapping": lambda data: data
        },
        "0080": {
            "name": "total_distance",
            "mapping": lambda data: int(data, base=16)
        },
        "0081": {
            "name": "province_id",
            "mapping": lambda data: int(data, base=16)
        },
        "0082": {
            "name": "city_id",
            "mapping": lambda data: int(data, base=16)
        },
        "0083": {
            "name": "license",
            "mapping": lambda data: int(data, base=16)
        },
        "0084": {
            "name": "license_color",
            "mapping": lambda data: int(data, base=16)
        },
    })
    audio_video_encoding: dict = field(default_factory=lambda: {
        # 音频编码方式
        1: "G.721",
        2: "G.722",
        3: "G.723",
        4: "G.728",
        5: "G.729",
        6: "G.711A",
        7: "G.711U",
        8: "G.726",
        9: "G.729A",
        10: "DVI4_3",
        11: "DVI4_4",
        12: "DVI4_8K",
        13: "DVI4_16K",
        14: "LPC",
        15: "S16BE_STEREO",
        16: "S16BE_MONO",
        17: "MPEGAUDIO",
        18: "LPCM",
        19: "AAC",
        20: "WMA9STD",
        21: "HEAAC",
        22: "PCM_VOICE",
        23: "PCM_AUDIO",
        24: "AACLC",
        25: "MP3",
        26: "ADPCMA",
        27: "MP4AUDIO",
        28: "AMR",
        # 透传
        91: "TRANSFER",
        # 视频编码方式
        98: "H.264",
        99: "H.265",
        100: "AVS",
        101: "SVAC",
    })
    audio_adoption_rate: dict = field(default_factory=lambda: {
        "00": "8KHZ",
        "01": "22.05KHZ",
        "02": "44.1KHZ",
        "03": "48KHZ",
    })
    audio_adoption_bit: dict = field(default_factory=lambda: {
        "00": "8bits",
        "01": "16bits",
        "02": "32bits",
    })


configs = Configs()
